#include <iostream>

#include <log.h>

class MyString {
public:
    MyString()
    {
        str = new char[stringLength];
        INNER_LOGGER() << "触发无参数构造函数(" << (void*)str << ")";
    }

    MyString(const MyString &other) : MyString()
    {
        INNER_LOGGER() << other.str << "触发复制构造函数";
        *this = other.str;
    }

    MyString(MyString &&other)
    {
        INNER_LOGGER() << other.str << "触发移动构造函数";
        str = other.str;
        other.str = nullptr;
    }

    MyString(const char *cstr) : MyString()
    {
        INNER_LOGGER() << cstr << "触发const char *参数构造函数";
        *this = cstr;
    }

    ~MyString()
    {
        if (str != nullptr) {
            INNER_LOGGER() << str << "(" << (void *)str << ")" << "触发析构函数";
            delete[] str;
        } else {
            INNER_LOGGER() << "触发析构函数，空字符串";
        }
    }

    MyString &operator =(const char *cstr)
    {
        for (int32_t i = 0; i < stringLength && (i <= 0 || cstr[i - 1] != 0); i++) {
            str[i] = cstr[i];
        }
        return *this;
    }

    operator const char *() = delete;

private:
    char *str;
    static constexpr int32_t stringLength = 100;
};

class MyStringDecorator {
public:
    template<class T>
    MyStringDecorator(T&& str) : mystr(std::forward<T>(str))
    {
        INNER_LOGGER() << "触发装饰器构造函数" << __PRETTY_FUNCTION__;
    }

    MyString Get()
    {
        INNER_LOGGER() << "获得装饰器字符串值类型";
        return mystr;
    }

    MyString& GetRef()
    {
        INNER_LOGGER() << "获得装饰器字符串左值引用";
        return mystr;
    }

    MyString&& GetRRef()
    {
        INNER_LOGGER() << "获得装饰器字符串右值引用";
        return std::move(mystr);
    }

private:
    MyString mystr;
};

int main()
{
    OUTER_LOGGER() << "变量构造";
    CODE_LOGGER(MyString ms;);
    CODE_LOGGER(MyString ms1 = "ms1";);
    CODE_LOGGER(MyString ms2("ms2"););
    CODE_LOGGER(MyString ms3 = ms2;);
    CODE_LOGGER(MyString ms4(MyString("ms4")););
    CODE_LOGGER(auto &&msrref1 = ms2;);
    CODE_LOGGER(MyString ms5(msrref1););

    OUTER_LOGGER() << "完美转发";
    CODE_LOGGER(MyStringDecorator msd("msd"););
    CODE_LOGGER(MyStringDecorator msd2(ms2););
    CODE_LOGGER(MyStringDecorator msd3(std::move(ms3)););
    CODE_LOGGER(auto &&msrref2 = ms2;);
    CODE_LOGGER(MyStringDecorator msd4(msrref2););

    {
        OUTER_LOGGER() << "auto &&延长临时变量生命周期";
        CODE_LOGGER(auto &&msrref = ms1;);
        CODE_LOGGER(LOGGER() << &ms1;);
        CODE_LOGGER(LOGGER() << &msrref;);
        CODE_LOGGER(MyStringDecorator msd4(msrref););
    }

    {
        OUTER_LOGGER() << "auto &&传参时被认为是auto类型";
        CODE_LOGGER(auto &&msrref = MyString("ms5"););
        CODE_LOGGER(LOGGER() << &msrref;);
        CODE_LOGGER(LOGGER() << typeid(msrref).name(););
        CODE_LOGGER(LOGGER() << typeid(MyString).name(););
        CODE_LOGGER(LOGGER() << typeid(MyString&).name(););
        CODE_LOGGER(LOGGER() << typeid(const MyString&).name(););
        CODE_LOGGER(LOGGER() << typeid(MyString&&).name(););
        CODE_LOGGER(MyStringDecorator msd5(msrref););
    }

    {
        OUTER_LOGGER() << "不接收返回值";
        CODE_LOGGER(msd.Get(););
        CODE_LOGGER(msd.GetRef(););
        CODE_LOGGER(msd.GetRRef(););
    }

    {
        OUTER_LOGGER() << "返回值为值类型";
        CODE_LOGGER(auto s1 = msd.Get(););
        CODE_LOGGER(const auto &s2 = msd.Get(););
        CODE_LOGGER(auto &&s3 = msd.Get(););
        VALUE_LOGGER(&s2);
        VALUE_LOGGER(&s3);
    }

    {
        OUTER_LOGGER() << "返回值为左值引用";
        CODE_LOGGER(auto s1 = msd.GetRef(););
        CODE_LOGGER(const auto &s2 = msd.GetRef(););
        CODE_LOGGER(auto &&s3 = msd.GetRef(););
        VALUE_LOGGER(&s2);
        VALUE_LOGGER(&s3);
    }

    {
        OUTER_LOGGER() << "返回值为右值引用";
        CODE_LOGGER(auto s1 = msd.GetRRef(););
        CODE_LOGGER(const auto &s2 = msd.GetRRef(););
        CODE_LOGGER(auto &&s3 = msd.GetRRef(););
        VALUE_LOGGER(&s2);
        VALUE_LOGGER(&s3);
    }

    OUTER_LOGGER() << "结束";
    return 0;
}
